/* vue3 和 vue2 的区别
  1. 语法上的区别
    => vue2 只有选项式 API【 options API 】
    => vue3 有 选项式API 和 组合式 API【 composition API 】
  2. 什么是 选项式API 和 组合式API
    => 选项式 API 就是按照内容功能的划分去书写 vue 所有需要用到的 状态/方法/侦听器/...
      new Vue({
        data () {},   存放所有状态( 数据 )
        methods: {},  存放所有的方法
        watch: {},    存放所有的侦听器
        computed: {}, 存放所有的计算属性
        ...
      })
      -> 优点:
        数据分类清晰
      -> 缺点:
        一套业务逻辑的 属性和方法和侦听器 等内容被分开放了
    => 组合式 API 就是按照业务逻辑的划分去书写 vue 所有需要用到的 状态/方法/侦听器/...
      书写一个 计数器hooks 【 推荐书写在 setup 外面 】
      function useCounter(init) {
        计数器需要用到的变量  const count = init
        计数器需要用到的方法  add 和 sub
        计数器需要用到的侦听器 watch( 'count' )
        ...
        return { 需要用到的东西 }
      }
      new Vue({
        setup () {
          接受 useCounter 的返回值
          const counter = useCounter(10)

          在 setup 内返回的东西, 就可以直接在 html 模板位置使用
          return { ...counter }
        }
      })
      -> 优点:
        一套逻辑内容放在一起, 后期迭代更新的时候, 快速定位当前逻辑所有使用的一切内容
        适用于逻辑复用
      -> 缺点:
        需要定义过多的 hooks, 组件引用的逻辑比较多
        对于一些复杂的逻辑, 可能几个小块的逻辑组合在一起使用【 多个 hooks 组合在一起使用 】
  3. 组合式 api 的变量使用
    => 当你在 setup 内定义响应式数据的时候, 有两种方式
      -> ref: 一般用于定义基本数据类型
        import { ref } from 'vue'
        function useCounter() {
          const count = ref(0) 一个响应式数据

          const add = () => {
            count.value++
          }
        }
        在 html 模板内可以直接使用 count
        在 hooks( 逻辑代码里面, 需要使用 count.value )
      -> reactive: 一般用于定义复杂数据类型
        import { reactive } from 'vue'
        function useUserList() {
          const listItem = reactive({ name: '电脑', price: 100.23 })  一个响应式数据

          const updateItem = () => {
            listItem.price = 200
          }
        }
        在 html 和 逻辑代码 内使用的时候, 都不需要添加 value
  4. 钩子函数的变化
    => vue2
      beforeCreate () {}
      created () {}
      beforeMount () {}
      mounted () {}
      beforeUpdate () {}
      updated () {}
      beforeDestroy () {}
      destroyed () {}
    => vue3
      -> 选项式API
        beforeCreate () {}
        created () {}
        beforeMount () {}
        mounted () {}
        beforeUpdate () {}
        updated () {}
        beforeUnmount () {}
        unmounted () {}
      -> 组合式API
        setup () {}
        剩余的钩子都以 API 的形式出现
  5. vue3 组合式 api 使用 钩子函数
    import { createApp, onMounted, onUnmounted } from 'vue'
    createApp({
      setup() {
        onMounted(() => {
          当页面挂载完毕后会触发的钩子函数
        })
        onUnmounted(() => {
          当前组件卸载时候会触发的钩子函数
        })
      }
    })
      .mount('#root')
  6. v-if 和 v-for 的优先级
    => Vue2 中 v-if 的优先级高于 v-for
    => Vue3 中 v-for 的优先级高于 v-if
  7. vue2 和 vue3 的 diff 语法不同
    => vue2 和 vue3 的状态更新都是根据 虚拟DOM 和 diff 算法来决定 页面上哪些内容需要更新
    => 什么是 虚拟DOM【 VNode 】
      -> 用一个抽象对象的形式来描述一个 节点 内容
      -> 例子:
        DOM
          <div><p>你好 世界</p></div>
        VNode
          {
            type: 'node',
            tagName: 'div',
            className: '',
            id: '',
            ...
            children: [
              {
                type: 'node',
                tagName: 'p',
                ...
                children: [
                  {
                    type: 'text',
                    value: '你好 世界',
                    ...
                  }
                ]
              }
            ]
          }
    => 当你需要更新视图的时候
      -> vue2 会把最新的结构组装成一个 新的虚拟DOM 树
        通过递归遍历的形式, 去比对, 找到哪一个节点变化了
        找到以后, 标记 patch
        所有的都遍历完毕以后, 找到需要更新的节点去进行更新
      -> vue3 会在一开始第一次渲染虚拟 DOM 树的时候, 给每一个节点添加 patchFlag 属性
        当视图需要更新的时候
        不会重新生成一个虚拟 DOM 树, 而是直接在原始 DOM 树的节点上把 patchFlag 变成 true
        并且把当前节点放在 patchFlags 数组内
        完毕以后, 直接按照 patchFlags 数据内记录的数据去更新节点
  8. 针对非响应式数据变化成为响应式数据
    => vue2 使用 vm.$set()
    => vue3 使用的事 toRef 和 toRefs 两个方法
      一般来说会在组件间传递数据的时候出现这个情况
      const 变量 = toRef(非响应式数据)
      const 变量 = toRefs(非响应式数据)
    => toRef 和 toRefs
      -> toRef 是变化对象内某一个数据, 出来的也是一个数据
      -> toRefs 是变化对象数据, 出来的是一个对象
  9. 数据劫持的区别
    => vue2 是 defineProperty + 发布订阅模式 实现的数据劫持
      -> 通过递归和遍历的方式来劫持 data 内的每一个属性
      -> 特点:
        后期追加的数据是没有劫持的, 不能响应式
    => vue3 是 Proxy 的方式来实现数据劫持( 数据代理 )
      -> 通过直接代理整个对象地址的方式来实现数据劫持
      -> 特点:
        后期追加的数据也是有劫持的, 可以实现响应式
  10. 核心插件 vuex 和 pinia
    => vue2 和数据状态管理器核心插件使用 vuex
      -> state
      -> mutations
      -> actives
      -> getters
      -> modules
    => vue3 的数据状态管理器核心插件使用 pinia【 理解为一个简化版本的 vuex 】
      -> state
      -> actives【 函数，方法 】
      -> getters【 计算属性 】
  11. TS 支持
    => vue2 对 TS 语法支持的不是很好
    => vue3 对 TS 语法支持的非常好
  12. vue-router 的变化
    => mode( 配置项 ) 属性的变化
      -> hash 模式和 history 模式
    => vue2
      new VueRouter({
        mode: 'hash',   'history'
        routes: []
      })
      没有任何额外多余的处理, 只是 url 地址渲染模式的不同
      如果你需要使用 history 模式的话需要服务端配合
    => vue3
      import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
      createRouter({
        mode: createWebHistory()
        routes: []
      })
      因为对应的 createWebHistory 做了一些逻辑和代理的处理
      不需要服务器配合, 直接就可以使用 history 模式
  13. 动态参数
    => vue2
      <div a="str"></div>
      <div :a="str"></div>
      <div :[:s1]="s2"></div>
      createApp({
        data () {
          return {
            s1: 'hello',
            s2: 'world'
          }
        }
      })
  14. v-memo 和 v-once
    => v-once: 一次性绑定, 永远成为一个静态的结构( patchFlag 标记为静态 )
    => v-memo: 涉及到的依赖变化的时候, 才会更新当前节点
      -> 例子:
        不管 name 还是 age 任何一个变化的时候, 都会更新当前节点
        <div>
          <p>{{ user.name }}</p>
          <p>{{ user.age }}</p>
        </div>
        只有 name 更新才会更新当前节点, 但是 age 更新的时候不会
        <div v-memo="[ user.name ]">
          <p>{{ user.name }}</p>
          <p>{{ user.age }}</p>
        </div>
        createApp({
          data () {
            return {
              user: { name: 'Jack', age: 18 }
            }
          }
        })
  15. vue-cli 和 vite
    => vue-cli
      -> vue 官方提供的构建工具【 内置构建非常全面, 选择是否要构建 router, 是否要构建 vuex, 是否要构建 ts, ... 】
      -> vue-cli 比较重量, 热重启, 更新速度比较慢
      -> 专门用来创建 vue 项目
    => vite
      -> 非官方提供的构建工具【 内置构建不够全面, 没有 router/vuex/... 】
      -> vite 比较轻量, 热重启, 更新速度比较快( 按需加载打包环境 )
      -> vite 是项目构建工具
*/
